home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
wcl-21.lha
/
wcl-2.1
/
src
/
compiler
/
common
/
link.lisp
< prev
next >
Wrap
Lisp/Scheme
|
1992-09-10
|
9KB
|
246 lines
;;; (C) Copyright 1990-1992 by Wade L. Hennessey. All rights reserved.
;;; Link a shared library.
;;; Only create symbols NOT found in other libraries.
(defun link-library (lib-name &key
other-lib-names
(predicates-file (tmp-file-name "preds.lisp") p?)
(data-file (tmp-file-name "data.c") d?))
(let ((*pic?* t))
(unwind-protect
(let ((*link-start-time* (get-universal-time))
(library (lookup-library lib-name)))
(create-library-aux-files
lib-name other-lib-names predicates-file data-file)
(ld-shared-library library predicates-file data-file)
library)
;; If caller supplies and aux file name, assume they want to keep it.
(unless p? (del-derived-files predicates-file))
(unless d? (del-derived-files data-file)))))
(defun create-library-aux-files (lib-name other-lib-names
predicates-file data-file)
(let* ((library (lookup-library lib-name))
(other-libraries (mapcar #'lookup-initialized-library
other-lib-names))
(symbol-table (clear-symbol-table (library-symbol-table library)))
(structures (new-structure-table))
(*const-labels* (make-hash-table :size 5000 :test #'equal)))
(clrhash (library-procedure-info library))
(clrhash (library-c-type-info library))
(setf (library-proclaims library) nil)
(link-msg "Reading symbol information")
(multiple-value-bind (lisp-init-thunks symbol-fixups)
(setup-application-symbols other-libraries symbol-table structures
(library-lisp-files library) library)
(compile-predicates-file
predicates-file other-libraries symbol-table structures)
(compile-library-data-file data-file other-libraries
symbol-table symbol-fixups
(library-init-thunk library)
lisp-init-thunks)
(write-library-info library)
lib-name)))
(defun link-executable (files &key
output
(lib-names *default-libraries*)
(dynamic-size 8192)
(static-size 512)
(main-function 'user::lmain)
(predicates-file (tmp-file-name
"preds.lisp") p?)
(data-file (tmp-file-name "data.c") d?)
(foreign-libs '("c" "m" )))
(unwind-protect
(let* ((*link-start-time* (get-universal-time))
(file-list (if (listp files) files (list files)))
(output (or output (make-pathname
:defaults (first file-list)
:type nil)))
(libraries (mapcar #'lookup-initialized-library
lib-names))
(all-libs
(append (mapcar #'(lambda (l)
(string-downcase (library-name l)))
libraries)
foreign-libs)))
(create-executable-aux-files
file-list libraries dynamic-size static-size main-function
predicates-file data-file)
(ld-executable output file-list predicates-file data-file all-libs)
output)
(unless p? (del-derived-files predicates-file))
(unless d? (del-derived-files data-file))))
(defun create-executable-aux-files (files libraries dynamic-size static-size
main-function
predicates-file data-file)
(let* ((symbol-table (new-symbol-table))
(structures (new-structure-table))
(*const-labels* (make-hash-table :size 5000 :test #'equal)))
(link-msg "Reading symbol information")
(multiple-value-bind (lisp-init-thunks symbol-fixups)
(setup-application-symbols libraries symbol-table structures files)
(compile-predicates-file
predicates-file libraries symbol-table structures)
(compile-executable-data-file data-file libraries
symbol-table symbol-fixups
lisp-init-thunks
main-function
dynamic-size static-size))))
(defun compile-predicates-file (predicates-file libs symbol-table structures)
(with-open-file (output predicates-file :direction :output)
(maphash #'(lambda (name info)
(declare (ignore name))
(write (application-structure-predicate info structures)
:stream output
:array t)
(terpri output))
structures))
(link-msg "Compiling predicates file")
(comf predicates-file)
;; Add new symbols created in preds file to symbol-table
(setup-application-symbols
libs symbol-table structures (list predicates-file)))
;;; lib_init_thunk (c-code)
;;; <c code register_symbols for each package in lib>
;;; <symbol-fixups>
;;; call-each-lib-file-init-thunk
(defun compile-library-data-file (data-file
other-libraries
symbol-table symbol-fixups
thunk-name library-lisp-thunks)
(link-msg "Writing data file")
;; Setup stream for EMIT-DATA
(with-open-file (*k-stream* data-file :direction :output)
(emit-symbol-table other-libraries symbol-table)
(emit-k "~%~A()~%{~%" thunk-name)
(emit-symbol-table-registration-code symbol-table)
(emit-k "~{ ~A~% ~}~%" symbol-fixups)
(dolist (lisp-thunk library-lisp-thunks)
(emit-k "~A(0);~%" (lisp->c-proc-name lisp-thunk)))
(emit-k "}~%"))
(link-msg "Compiling data file")
(invoke-c-compiler data-file))
;;; main (c-code)
;;; start_initialization(sizes);
;;; <c code register_symbols for each package in app>
;;; <symbol-fixups>
;;; call-each-lib-init-thunk
;;; call-each-app-file-init-thunk [LISP]
;;; (catch (main-func)) [LISP]
(defun compile-executable-data-file (data-file
libraries
symbol-table symbol-fixups
application-lisp-thunks
main-function
dynamic-size static-size)
(link-msg "Writing data file")
;; Setup stream for EMIT-DATA
(with-open-file (*k-stream* data-file :direction :output)
(emit-symbol-table libraries symbol-table)
(emit-k "main(argc,argv) int argc; char *argv[]; {~%")
(emit-k "start_initialization(argc,argv,~D,~D);~%"
dynamic-size static-size)
(emit-symbol-table-registration-code symbol-table)
(emit-k "~{ ~A~% ~}~%" symbol-fixups)
(dolist (lib libraries)
(emit-k "~A();~%" (library-init-thunk lib)))
(dolist (lisp-thunk application-lisp-thunks)
(emit-k "~A(0);~%" (lisp->c-proc-name lisp-thunk)))
(emit-k "p_lsp_START_2DAPPLICATION(1,LREF(~A));~%"
(lisp->c-symbol-name main-function))
(emit-k "}~%"))
(link-msg "Compiling data file")
(invoke-c-compiler data-file))
(defun ld-shared-library (library predicates-file data-file)
(link-msg "Linking shared library")
(shell (format nil "ld -o ~A ~{ ~A ~} ~A ~A~%"
(library-unix-name library)
(library-all-object-files library)
(binary-pathname predicates-file)
(binary-pathname data-file))))
(defun ld-executable (output-file files preds-file data-file unix-libs)
(invoke-linker
(format nil
"~A -o ~A ~A ~A ~{~A ~} -L~A/lib ~{-l~A ~}"
(if *profile?* "-p " "")
(namestring output-file)
(namestring (merge-pathnames ".o" preds-file))
(namestring (merge-pathnames ".o" data-file))
(mapcar #'binary-pathname files)
*root-directory*
unix-libs))
(link-msg "done")
output-file)
(defun invoke-c-compiler (file &optional
(output (merge-pathnames ".o" file)))
(let ((status
(funcall
#'shell
(format nil "~A -c -I~A/include -o ~A ~A"
(basic-cc-string)
(namestring *root-directory*)
(namestring output)
(namestring file)))))
(unless (successful-status? status)
(error "Failed to compile file: ~S, status: ~D" file status))
status))
(defun basic-cc-string ()
(let ((c-compiler (machine-c-compiler *target-machine*)))
(concatenate 'string
(c-compiler-command c-compiler)
" "
(if (config-cc-debug-info? *config*)
(c-compiler-debug-switch c-compiler)
nil)
" "
(if (or (not (config-cc-debug-info? *config*))
(c-compiler-debug-optimized? c-compiler))
(svref (c-compiler-optimizer-switches c-compiler)
(config-cc-optimizer-level *config*))
"")
" "
(if *pic?*
(c-compiler-position-independent-code-switch
(machine-c-compiler *target-machine*))
""))))
(defun invoke-linker (cmd)
(let ((status
(funcall #'shell
(concatenate 'string
(machine-linker-command *target-machine*)
" " cmd " "
(machine-link-libraries *target-machine*)))))
(unless (successful-status? status)
(error "Failed to link: ~S, status: ~D" cmd status))
status))
(defun successful-status? (s)
(= s 0))
(defun elapsed-link-time ()
(- (get-universal-time) *link-start-time*))
(defun link-msg (msg)
(format t "~D seconds: ~A~%" (elapsed-link-time) msg))
(defun c-pathname (name)
(merge-pathnames ".c" name))
(defun binary-pathname (name)
(merge-pathnames ".o" name))